import { routerRedux } from 'dva/router'
import * as update from 'immutability-helper'
import { getLocalStorage, getDocumentProperty, config, Logger, strEnum, settings } from '../utils';
import { auth, login, logout } from '../services/app';

// typescript 定义
import { Model } from 'dva';
import { Dispatch } from 'redux';
import { History } from 'history';

const { prefix, indexPage } = config;

// logger
const logger = Logger.get('models_app');

export const namespace = 'app';

export const Action = strEnum([
  'auth',
  'login',
  'logout',
  'changeNavbar',
  'checkRender',
  'authSuccess',
  'authFailure',
  'switchSider',
  'switchTheme',
  'switchMenuPopver',
  'handleNavbar',
  'handleNavOpenKeys',
  'rendered'
]);

export interface State {
  isAuthenticated: boolean,
  user: any,
  menuPopoverVisible: boolean,
  siderFold: boolean,
  darkTheme: boolean,
  isNavbar: boolean,
  navOpenKeys: Array<string>,
  isRendered: boolean
};
let navOpenKeys: string = getLocalStorage(`${prefix}navOpenKeys`);
if (!navOpenKeys) {
  navOpenKeys = "[]";
}

const state: State = {
  isAuthenticated: false,
  user: {},
  menuPopoverVisible: false,
  //siderFold: getLocalStorage(`${prefix}siderFold`) === 'true',
  //darkTheme: getLocalStorage(`${prefix}darkTheme`) === 'true',
  siderFold: false,
  darkTheme: false,
  isNavbar: getDocumentProperty('body', 'clientWidth') < 769,
  navOpenKeys: JSON.parse(navOpenKeys) || [],
  isRendered: false
};

const app: Model = {
  namespace,
  state,
  subscriptions: {
    // 订阅url跳转时的处理
    setup({ dispatch, history, intl }: { dispatch: Dispatch<any>, history: History, intl: any}) {
      logger.debug(intl);
      // 判断是否是服务器端渲染
      if (!settings.isServer) {
        let tid;
        const resize = () => {
            clearTimeout(tid);
            tid = setTimeout(() => {
              dispatch({ type: Action.changeNavbar })
            }, 300)
        }
        window.onresize = resize;
        const unlistener = history.listen(location => {
          // 根据当前url判断
          const { pathname } = location;
          if (pathname === '/') {
            // 跳转到主页
            dispatch(routerRedux.push(indexPage));
          } else {
            dispatch({
              type: Action.auth
            });
            // // 设置渲染状态
            // dispatch({
            //   type: Action.checkRender
            // })
          }
        });
        return () => {
          window.removeEventListener('onresize', resize, true);
          unlistener();
        };
      }
    },
  },
  effects: {
    *[Action.auth] ({ payload }: any, { call, put, select }): Generator {
      logger.info('auth');
      // pathname: 路径
      // from: 跳转前画面路径
      const state = yield select(state => state);
      logger.log(state);
      const { routing: { locationBeforeTransitions: { pathname, query: { from } } } }
          = yield (select(state => state));
      logger.log(pathname);
      // 登陆验证，返回用户信息
      const result = yield call(auth, payload);
      const { success, data } = result;
      logger.log(success);
      logger.log(data);
      if (success && data) {
        yield put({
          type: Action.authSuccess,
          payload: data,
        })
        // 如果是当前页尾login的话，
        // 跳转到dashboard
        if (pathname === '/login') {
          if (from) {
            logger.log('push ' + from) ;
            yield put(routerRedux.push(from));
          } else {
            yield put(routerRedux.push(indexPage));
          }
        }
      } else {
        yield put({
          type: Action.authFailure,
          payload: data,
        })
        // 登陆失败
        if (pathname !== '/login') {
          let from = pathname;
          yield put(routerRedux.push(`/login?from=${from}`));
        }
      }
    },
    *[Action.logout] ({ payload }: any, { call, put }): Generator {
      // 登出
      const result = yield call(logout, payload);
      const { success } = result;
      if (success) {
        yield put({ type: 'auth' });
      } else {
        throw (result);
      }
    },
    *[Action.changeNavbar] ({ payload }: any, { put, select }): Generator {
      // 改变导航栏
      const { app } = yield (select(store => store));
      const isNavbar = getDocumentProperty('body', 'clientWidth') < 769;
      if (isNavbar !== app.isNavbar) {
        yield put({ type: 'handleNavbar', payload: isNavbar });
      }
    },
    /**
     * 检查是否已经渲染过
     * @param param0
     * @param param1
     */
    *[Action.checkRender] ({ payload }: any, { put, select }): Generator {
      const { app: { isRendered } } = yield (select(store => store));
      if (!isRendered) {
        // 如果没有渲染过的话，设置渲染状态
        yield put({
          type: Action.rendered
        });
      }
    }
  },
  reducers: {
    [Action.authSuccess] (state: State, { payload: user }: { payload: {} }): State {
      // 登录验证成功后更新state
      // 更新成登陆成功状态，更新用户信息
      return update(state, {
        isAuthenticated: {
          $set: true
        },
        user: {
          $set: user
        },
        isRendered: {
          $set: true
        }
      });
    },
    [Action.authFailure] (state: State): State {
      // 登录验证失败后更新state
      // 修改成没登陆状态
      return update(state, {
        isAuthenticated: {
          $set: false
        },
        isRendered: {
          $set: true
        }
      });
    },
    [Action.switchSider] (state: State): State {
      // 切换侧边栏
      const { siderFold } = state;
      localStorage.setItem(`${prefix}siderFold`, !siderFold ? '1' : '0');
      return update(state, {
        siderFold: {
          $set: !siderFold
        }
      });
    },
    [Action.switchTheme] (state: State): State {
      // 切换主题
      const { darkTheme } = state;
      localStorage.setItem(`${prefix}darkTheme`, !darkTheme ? '1' : '0');
      return update(state, {
        darkTheme: {
          $set: !darkTheme
        }
      });
    },
    [Action.switchMenuPopver] (state: State): State {
      // 切换菜单
      const { menuPopoverVisible } = state;
      return update(state, {
        menuPopoverVisible: {
          $set: !menuPopoverVisible
        }
      });
    },
    [Action.handleNavbar] (state: State, { payload }: { payload: boolean }): State {
      // 设置导航栏
      return update(state, {
        isNavbar: {
          $set: payload
        }
      });
    },
    [Action.handleNavOpenKeys] (state: State, { payload: navOpenKeys }: { payload: Array<string>}): State {
      // 导航栏的展开相关
      return update(state, {
        navOpenKeys: {
          $set: navOpenKeys
        }
      });
    },
    [Action.rendered] (state: State): State {
      // 设置为已渲染
      return update(state, {
        isRendered: {
          $set: true
        }
      });
    }
  }
};

export default app;
